package com.yongqi.duocai.controller;

import com.alibaba.fastjson.JSONObject;
import com.yongqi.duocai.entity.User;
import com.yongqi.duocai.entity.result.UserResult;
import com.yongqi.duocai.exception.BusinessException;
import com.yongqi.duocai.exception.ResponseEnum;
import com.yongqi.duocai.service.UserService;
import com.yongqi.duocai.utils.JsonResult;
import com.yongqi.duocai.utils.JwtUtils;
import com.yongqi.duocai.utils.RestTemplateUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.codec.binary.Base64;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.Base64Utils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.spec.AlgorithmParameterSpec;
import java.util.concurrent.TimeUnit;

/**
 * 1.描述（@desc）：微信登陆
 * 2.作者（@author）：夏亮辉
 * 3.日期（@date）：2021年06月22  9:27
 * 4.版本（@version）：1.0.0
 * 5.版权：
 */
@RestController
@Api(tags = "WeChatController")
public class WeChatController {

    @Autowired
    private UserService userService;

    @Value("${weixinconfig.weixinappID}")
    private String appId;

    @Value("${weixinconfig.weixinappSercret}")
    private String appSecret;

    @PostMapping("/wxLogin")
    @ApiOperation(value = "微信登陆")
    public JsonResult wxLogin(String code, String rawData){

        JsonResult jsonResult = new JsonResult();
        // 登陆凭证校验。通过 wx.login 接口获得临时登陆凭证 code 后传到开发者服务器调用此接口完成登陆流程
        String url = "https://api.weixin.qq.com/sns/jscode2session";
        MultiValueMap<String, Object> param = new LinkedMultiValueMap<>();
        param.add("appid",appId);
        param.add("secret",appSecret);
        param.add("js_code",code);
        param.add("grant_type","anuthorization_code");

        // RestTemplate 的请求
        // 开发者服务器 登陆凭证校验接口 appid + appsercret + code
        JSONObject forObject = RestTemplateUtil.doPost(url,param);
        System.out.println(forObject);

        // 接收微信接口服务 获取返回的参数
        String openid = forObject.getString("openid");
        if(StringUtils.isEmpty(openid)){

            throw new BusinessException(ResponseEnum.APPID_INVALID_ERROR);

        }

        String sessionKey = forObject.getString("session_key");
        System.out.println(sessionKey);

        // 用户非敏感信息
        JSONObject rawDataJson = JSONObject.parseObject(rawData);

        System.out.println(rawDataJson.toJSONString());
        // 判断用户是否存在
        User condition = userService.selectByOpenId(openid);
        Integer userID = null;

        if(condition == null){
            // 用户信息入库
            String nickName = rawDataJson.getString("nickName");
            String phone = rawDataJson.getString("phone");

            // 添加用户信息
            User user = new User();
            user.setWxName(nickName);
            user.setOpenid(openid);
            userService.save(user);

            userID = user.getId();
        }else {
            userID = condition.getId();
        }

        // 组装返回的用户对象
        UserResult result = new UserResult();
        result.setUserId(userID);
        result.setToken(JwtUtils.createToken(userID));

        jsonResult.setCode(200);
        jsonResult.setData(result);
        jsonResult.setMessage("登录成功");
        return jsonResult;
    }

    @PostMapping("/getPhone")
    @ApiOperation(value = "获取用户手机号")
    public JsonResult  docodeWxAppPhone(String encrypted, String iv, String code){
        JsonResult jsonResult = new JsonResult();
        // 登陆凭证校验。通过 wx.login 接口获得临时登陆凭证 code 后传到开发者服务器调用此接口完成登陆流程
        String url = "https://api.weixin.qq.com/sns/jscode2session";
        MultiValueMap<String, Object> param = new LinkedMultiValueMap<>();
        param.add("appid",appId);
        param.add("secret",appSecret);
        param.add("js_code",code);
        param.add("grant_type","anuthorization_code");

        // RestTemplate 的请求
        // 开发者服务器 登陆凭证校验接口 appid + appsercret + code
        JSONObject forObject = RestTemplateUtil.doPost(url, param);
        System.out.println(forObject);

        // 接收微信接口服务 获取返回的参数
        String openid = forObject.getString("openid");
        if (StringUtils.isEmpty(openid)) {
            throw new BusinessException(ResponseEnum.APPID_INVALID_ERROR);
        }

        String sessionkey = forObject.getString("session_key");
        System.out.println(sessionkey);
        try {
            // 解密
            byte[] encrypData = Base64.decodeBase64(encrypted);
            byte[] ivData = Base64.decodeBase64(iv);
            byte[] sessionKey = Base64.decodeBase64(sessionkey);
            AlgorithmParameterSpec ivSpec = new IvParameterSpec(ivData);
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            SecretKeySpec keySpec = new SecretKeySpec(sessionKey, "AES");
            String resultString = null;
            try{
                cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
                resultString = new String(cipher.doFinal(encrypData), "UTF-8");
            } catch (Exception e){
                // 解密
                encrypData = Base64.decodeBase64(encrypted);
                ivData = Base64.decodeBase64(iv);
                sessionKey = Base64.decodeBase64(sessionkey);
                ivSpec = new IvParameterSpec(ivData);
                cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
                keySpec = new SecretKeySpec(sessionKey, "AES");
                cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
                cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
                resultString = new String(cipher.doFinal(encrypData), "UTF-8");
            }
            JSONObject object = JSONObject.parseObject(resultString);
            System.out.println(object.toJSONString());
            // 拿到手机号码
            String phone = object.getString("phoneNumber");
            System.out.println(phone);
            if(phone != null){
                jsonResult.setCode(200);
                jsonResult.setData(object);
            }else {
                jsonResult.setCode(200);
                jsonResult.setMessage("微信手机号为空。");
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return jsonResult;
    }

}
